
#include "gmatlab.h"

// mxArray * g_object_matlab_new(GType type, mxArray *paramCellArray)
void mexFunction(int nlhs, mxArray *lhs[], int nrhs, mxArray *rhs[])
{
  GParamSpec *pspec;
  GObjectClass *cls;
  GObject *obj;
  GType gtype;
  guint num, i;
  
  // Check arguments
  if (nrhs != 2) g_matlab_error("gmatlab:numArg", "g_object_matlab_new() takes 2 arguments");
  if (nlhs != 1) g_matlab_error("gmatlab:numRet", "g_object_matlab_new() has 1 return value");
  if (!mxIsCell(rhs[1])) g_matlab_error("gmatlab:badArray", "g_object_matlab_new: Arg 2 must be cell array");
  num = mxGetNumberOfElements(rhs[1]);
  if (num % 2) g_matlab_error("gmatlab:badArray", "g_object_matlab_new: Construction parameter name/values must be in pairs (%d given)", num);
  num /= 2;

  // Convert arguments
  g_matlab_escape_init();
  GParameter *params = g_new0(GParameter, num);
  g_matlab_cleanup_add(g_free, params);
  gtype = g_matlab_mxArray_get_gtype(rhs[0]);
  if (!G_TYPE_IS_OBJECT(gtype)) g_matlab_error("gmatlab:systemError", "g_object_matlab_new: Requested gtype is not a GObject");
  cls = g_matlab_cleanup_add(g_type_class_unref, g_type_class_ref(gtype));
  for (i=0; i < num; i++)
  {
    mxArray *mxName = mxGetCell(rhs[1], 2*i);
    if (mxGetClassID(mxName) != mxCHAR_CLASS) g_matlab_error("gmatlab:badType", "g_object_matlab_new: Element %d must be a char parameter name", i);
    if (mxGetNumberOfElements(mxName) == 0) g_matlab_error("gmatlab:badArray", "g_object_matlab_new: Element %d is empty", i);
    params[i].name = g_matlab_mxArray_get_utf8(mxName);
    g_matlab_cleanup_add(g_free, params[i].name);

    pspec = g_object_class_find_property(cls, params[i].name);
    if (pspec == NULL)
      g_matlab_error("gmatlab:notFound", "g_object_matlab_get_property: Object does not have property %s", params[i].name);
    
    g_value_from_mxArray(&(params[i].value), mxGetCell(rhs[1], 2*i+1));
    g_matlab_cleanup_add((GHookFunc)g_value_unset, &(params[i].value));
  }
  
  // Call function
  obj = g_object_newv(gtype, num, params);
  g_return_if_fail(obj != NULL);
  
  // Prepare return value
  lhs[0] = g_object_matlab_wrap(obj);
  g_object_unref(obj);

  g_matlab_escape_clear();
  g_matlab_cleanup();
}
